#include"tcp_connection.h"
#include"epoll.h"
#include"eventloop.h"
#include"log.h"
#include"util.h"

#include<string>
#include<cstring>
#include<functional>

TcpConnection::TcpConnection(EventLoop *base, int fd):m_loop(base),
    m_connfd(fd),
    m_channel_ptr(new Channel(base,fd)),
    m_conn_state(ConnectionState::H_CONNECTED),
    m_error(false)
{   
    m_channel_ptr->setReadHandler(std::bind(&TcpConnection::handleRead,this));
    m_channel_ptr->setWriteHandler(std::bind(&TcpConnection::handleWrite,this));
    m_channel_ptr->setErrorHandler(std::bind(&TcpConnection::handleError,this));
    m_channel_ptr->setConnHandler(std::bind(&TcpConnection::handleConn,this));
}
EventLoop* TcpConnection::getLoop(){
    return m_loop;
}
void TcpConnection::handleClose(){
    m_conn_state = ConnectionState::H_DISCONNECTED;
    m_loop->remove_event(m_channel_ptr);
}
void TcpConnection::set_event(uint32_t ev){
    m_channel_ptr->setEvents(ev);
}
void TcpConnection::register_event(){
    m_loop->add_event(m_channel_ptr,2000);
}

void TcpConnection::handleRead(){
    bool zero = false;
    int read_sum = readn(m_connfd,m_inBuffer,zero);
    //如果zero==true,表示连接出现问题,可能是连接断开或者其他...
    if(read_sum<0 || zero){
        record()<<"connfd read error";
        m_error=true;
        m_conn_state=ConnectionState::H_DISCONNECTED;
        handleError();
        return;
    }
    record()<<"request: "<<m_inBuffer;
    if(m_conn_state!=ConnectionState::H_CONNECTED){
        m_inBuffer.clear();
        return;
    }
    int ret=m_callback();
    if(ret==0 && m_conn_state==ConnectionState::H_CONNECTED){
        if(m_outBuffer.size()>0){
            handleWrite();
        }
        else{
            handleError();
            clearAndError();
        }
    }
}
void TcpConnection::handleWrite(){
    record()<<"handler write";
    if(!m_error && m_conn_state!=ConnectionState::H_DISCONNECTED){
        uint32_t &ev=m_channel_ptr->getEvents();
        if(writen(m_connfd,m_outBuffer)<0){
            record()<<"tcp_conn write error";
            ev=0;
            m_error=true;
        }
        if(m_outBuffer.size()>0){
            ev|=EPOLLIN;
        }
    } 
}
void TcpConnection::handleError(){
    string short_msg(" Bad Request");
    char send_buff[4096];
    string body_buff, header_buff;
    //http 响应报文主体
    body_buff += "<html><title>搞错啦</title>";
    body_buff += "<body bgcolor=\"ffffff\">";
    body_buff += to_string(400) + short_msg;
    body_buff += "<hr><em> C++11 WebServer</em>\n</body></html>";
    //http 响应报文头部
    header_buff += "HTTP/1.1 " + to_string(400) + short_msg + "\r\n";
    header_buff += "Content-Type: text/html\r\n";
    header_buff += "Connection: Close\r\n";
    header_buff += "Content-Length: " + to_string(body_buff.size()) + "\r\n";
    header_buff += "Server: C++11 WebServer\r\n";
    header_buff += "\r\n";
    //错误处理而已，就不处理writen返回值了
    sprintf(send_buff, "%s", header_buff.c_str());
    writen(m_connfd, send_buff, strlen(send_buff));
    sprintf(send_buff, "%s", body_buff.c_str());
    writen(m_connfd, send_buff, strlen(send_buff));
}
void TcpConnection::handleConn(){
    m_seperate();
    uint32_t &events=m_channel_ptr->getEvents();
    if(!m_error && m_conn_state==ConnectionState::H_CONNECTED){
        events|=EPOLLET|EPOLLIN;
        set_event(events);
        m_loop->update_event(m_channel_ptr,2000);
    }
    else{
        record()<<"handle conn error"<<m_conn_state<<" "<<m_error;
        m_conn_state=ConnectionState::H_DISCONNECTED;
    }
}